package manet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import manet.comm.Communicator;
import manet.comm.DefaultCommunicator;
import manet.comm.MulticastIPCommunicator;
import manet.comm.UnicastIPCommunicator;
import manet.crypto.CryptoGenerator;
import manet.gui.InfoPanel;
import manet.gui.RobotSimFrame;

/**
 * The controller class will instantiate and initialize nodes that
 * are able to communicate via cryptographic protocols.
 * @author grin0077 stra0556
 *
 */
public class Controller {

	/** Number of milliseconds between updates  */
	static final int UPDATE_FREQUENCY = 5;

	/** The collection of nodes that will be used throughout the simulation */
	private static List<Node> nodes = Collections.synchronizedList(new ArrayList<Node>());

	/** The panel containing the table of information */
	private static InfoPanel myinfoPanel = new InfoPanel();

	/** The frame that will hold to coordinate information for the simulation */
	private static RobotSimFrame myFrame = new RobotSimFrame();	

	/**
	 * @param args the commandline parameters
	 */
	public static void main(String[] args) {

		System.out.println("||| STARTING SIMULATION |||");

		//unicastCommTest();
		//multicastCommTest();
		//System.exit(0);


		CryptoGenerator c = new CryptoGenerator();
		Node testNode = new Node("localhost", 8000, new DefaultCommunicator("A"), c);
		nodes.add(testNode);
		testNode = new Node("localhost", 8001, new DefaultCommunicator("B"), c);
		nodes.add(testNode);
		testNode = new Node("localhost", 8002, new DefaultCommunicator("C"), c);
		nodes.add(testNode);
		testNode = new Node("localhost", 8003, new DefaultCommunicator("D"), c);
		nodes.add(testNode);
		testNode = new Node("localhost", 8004, new DefaultCommunicator("E"), c);
		nodes.add(testNode);
		testNode = new Node("localhost", 8005, new DefaultCommunicator("F"), c);
		nodes.add(testNode);


		for(;;){

			/* Pull the information from the server */
			updateNodes();

			/* Update the GUI as needed */
			updateGUI();

			/* Move the nodes along */
			moveNodes();
			
			try {
				Thread.sleep(UPDATE_FREQUENCY);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 *  Method used to move the nodes each turn 
	 */
	static void moveNodes(){

		/* Loop through each node in our list */
		for( Node bot : nodes){

			/* Have the node do a random move */
			bot.randomMove();
		}
	}

	/**
	 * Update the nodes by pulling the information from the server
	 * then generating the new groups 
	 */
	static void updateNodes(){

		/* Loop through each node */
		for( Node bot : nodes){
			/* Pull the data from the server */
			bot.updateData();

			/* Zero the group id*/
			bot.zeroize();
		}
		int nextGroupID = 1;

		/* Zip through all the nodes and figure out the new group */
		for( Node bot : nodes){

			/* Add the new group */
			if( bot.getGroupID() == 0 ){
				/* Set the group and propograte it down */
				bot.setGroupID( nextGroupID, nodes );
				nextGroupID++;
			}

		}
	}

	/**
	 * Updates the GUI frame with the new positions as well as the table
	 * with the group info 
	 */
	static void updateGUI(){

		/* Update with the positions and draw the lines */
		myFrame.updateGUI(nodes);

		/* Update the table */
		myinfoPanel.updateTable(nodes);
	}
	
	/** Runs a simple multicast communicator test */
	static void multicastCommTest() {
		Communicator comm1 = new MulticastIPCommunicator("192.168.239.1", "239.239.239.239", 5000);
		Communicator comm2 = new MulticastIPCommunicator("192.168.239.2", "239.239.239.239", 5000);
	
		comm2.setListeningState(true);
		
		System.out.println("comm1 listen: " + comm1.isListening());
		System.out.println("comm2 listen: " + comm2.isListening());
		
		comm1.sendMessage("TEST");
		
		
		for(int i=1; i < 5; i++) { 
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
		System.out.println(comm2.newMessagesAvailable());
		System.out.println(comm2.getQueuedMessage());
	}
	
	/** Runs a simple unicast communicator test */
	static void unicastCommTest() {
		Communicator comm1 = new UnicastIPCommunicator("192.168.168.1", 5000);
		Communicator comm2 = new UnicastIPCommunicator("192.168.168.2", 5000);
		
		comm2.setListeningState(true);
		
		System.out.println("comm1 listen: " + comm1.isListening());
		System.out.println("comm2 listen: " + comm2.isListening());
		
		comm1.sendMessage("TESTING2", "255.255.255.255");
		
		for(int i=1; i<5; i++) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println(comm2.newMessagesAvailable());
		System.out.println(comm2.getQueuedMessage());
	}
}
